#ifndef __ASSEMBLY_H__
#define __ASSEMBLY_H__

#include "Face.h"
#include "Material.h"
#include "Matrix4D.h"
#include "Vertex.h"

#include <list>
#include <string>
#include <iostream>
#include <sstream>

#include <GL/gl.h>

using std::list;
using std::string;
using std::ostream;

using std::cout;
using std::endl;

#include <stdexcept>
using std::runtime_error;

class Assembly
{
public:
	// ctor
	Assembly();
	
	Assembly(const Vertex& pos);
	Assembly(float x, float y, float z);
	
	Assembly(const Vertex& pos, const Vertex& rot);
	Assembly(float x, float y, float z,
	         float a, float b, float g);
	         
	// dtor
	virtual ~Assembly();
	
	// getter/setter for position, angles and scale
	const Vertex& position() const;
	Vertex& position();
	const Vertex& rotation() const;
	Vertex& rotation();
	const Vertex& scale() const;
	Vertex& scale();
	
	// insert a child
	void addPart(Assembly* child);
	
	// add a face to the object
	void addFace(Face* face);
	
	// draw the Assembly, cannot be "const"
	// due to display list invalidation
	void draw();
	
	// name setter/getter
	const string& name() const;
	string& name();
	
	// material setter/getter
	string& material();
	const string& material() const;
	
	// get a deep Obj-Dump of the assembly
	// (obj, material)
	void exportObj(ostream& os, ostream& ms);
	
protected:
	// translate the origin, scale, then rotate
	// with the Translate-Scale-Rotate-Matrix,
	// eventually do the deep dump of the object
	void exportObj(ostream& ss, const Matrix4D& parent_tsr, int& vc, int& nc);
	// do the flat dump of the TSR'd object, counting vertex and normals
	void dump_me(ostream& ss, const Matrix4D& parent_tsr, int& vc, int& nc);
	
	
	// set child depth (recursive)
	void setDepth(Assembly* child, unsigned depth);
	
	void draw_me();
	void draw_children();
	
	// update DLists recursively
	void update_DL_rec(Assembly* ptr);
	// update own display list
	void update_DL();
	// update display list
	void update_cDL();
	
	virtual void update_vertex();
	void update_material();
	
	void print(Assembly* ptr);
	
	// position, X-, Y-, Z-value
	// rotation about X-, Y- and Z-Axis
	// scale factors
	Vertex m_position, m_rotation, m_scale;
	
	// display lists for the object and it's children
	int m_DL_id, m_cDL_id;
	// modification flags for the object and it's children
	bool m_DL_mod, m_cDL_mod;
	
	// name of the object
	string m_name;
	
	// material
	string m_matname;
	// modification flags for vertex and material
	bool m_v_mod, m_m_mod;
	
	// depth-level of the Assembly (0 == scene)
	unsigned m_depth;
	
	// pointer to the parent-Assembly
	Assembly* m_parent;
	
	// list of children
	list<Assembly*> m_parts;
	
	// list of faces
	list <Face*> m_face;
	
};

#endif

